<?php

namespace Packages\User\Services;

use App\Tools\Common;
use Packages\User\Models\UserInfoModel;
use Packages\User\Models\UserLoginModel;
use Packages\User\Models\UserTokenModel;
use Exception;

class UserService
{

    /********************** 业务逻辑层 *********************/

    /**
     * 注册
     * @param $data
     * @return array
     */
    public function register($data)
    {

        // 注册方式检测
        if (empty($data['username']) && empty($data['bind_phone'])) {
            return ['status' => false, 'msg' => '注册方式错误!'];
        }

        // 用户名重复检测
        if (@$data['username']) {

            $username = UserLoginModel::where('username', $data['username'])->first();

            if ($username) {
                return ['status' => false, 'msg' => '用户名已存在!'];
            }

            // 密码检测
            if (empty($data['password'])) {
                return ['status' => false, 'msg' => '使用用户名注册时必须设置登录密码!'];
            }
        }

        // 手机号重复检测
        if (@$data['bind_phone']) {
            $bind_phone = UserLoginModel::where('bind_phone', $data['bind_phone'])->first();
            if ($bind_phone) {
                return ['status' => false, 'msg' => '手机号已注册!'];
            }
        }

        $uuid = Common::getUuid();

        // 密码加密
        $data['password'] = Common::cryptString($uuid, $data['password']);

        // 生成用户基本信息
        $userInfo = UserInfoModel::create([
            'guid' => $uuid,
            'nick_name' => $data['nick_name'] ?? 'u' . mt_rand(), // 昵称
            'gender' => $data['gender'] ?? 0, // 0 未知 1 男 2 女
            'avatar' => $data['avatar'] ?? '', // 头像
            'birthday' => $data['birthday'] ?? null, // 生日
            'type' => $data['type'], // 1 普通用户 2 管理员 3 合作用户/商家 
            'app_id' => $data['app_id'] ?? '0', // 应用id
            'meta' => $data['meta'] ?? (object)[], // 更多信息
        ]);

        // 生成用户登陆信息
        $userLogin = UserLoginModel::create([
            'user_id' => $uuid,
            'username' => $data['username'] ?? null,
            'password' => $data['password'],
            'bind_email' => $data['bind_email'] ?? null,
            'bind_phone' => $data['bind_phone'] ?? null,
            'status' => 1, // 1 正常 2 禁用 3 封禁 4 注销
            'type' => $data['type'], // 1 普通用户 2 管理员 3 合作用户/商家 
            'app_id' => $data['app_id'] ?? '0', // 应用id
        ]);

        // 触发用户注册事件
        event(new \App\Events\User\UserRegisterEvent($userInfo, $userLogin));

        return ['status' => true, 'data' => $userInfo];
    }

    /**
     * 登录
     * @param $data
     * @return array
     */
    public function login($data)
    {
        // 登录账号查询
        switch (@$data['method']) {
            case 'username': // 用户名+密码登录
                if (empty($data['password'])) {
                    return ['status' => false, 'msg' => '密码不能为空!'];
                }

                $userLogin = UserLoginModel::where('username', $data['username'])->first();
                break;
            case 'bind_phone': // 手机号+验证码登录
                if (empty($data['code'])) {
                    return ['status' => false, 'msg' => '验证码不能为空!'];
                }

                $userLogin = UserLoginModel::where('bind_phone', $data['bind_phone'])->first();
                break;
            case 'phone_pass': // 手机号+密码登录
                if (empty($data['password'])) {
                    return ['status' => false, 'msg' => '密码不能为空!'];
                }

                $userLogin = UserLoginModel::where('bind_phone', $data['bind_phone'])->first();
                break;
            case 'email_pass': // 邮箱+密码登录
                $userLogin = UserLoginModel::where('bind_email', $data['bind_email'])->first();
                break;
            default:
                return ['status' => false, 'msg' => '登录方式错误!'];
        }

        // 账号检测
        if (empty($userLogin)) {
            return ['status' => false, 'msg' => '账号不存在!'];
        }

        // 密码检测
        if (@$data['password']) {
            // 密码加密
            $password = Common::cryptString($userLogin->user_id, $data['password']);

            if ($password != $userLogin->password) {
                return ['status' => false, 'msg' => '密码错误!'];
            }
        }

        // 账号状态检测
        switch ($userLogin->status) {
            case 1: // 正常
                break;
            case 2: // 禁用
                return ['status' => false, 'msg' => '账号已被禁用, 无法登录!'];
            case 3: // 封禁
                return ['status' => false, 'msg' => '账号违规, 暂时无法登录!'];
            case 4: // 注销
                return ['status' => false, 'msg' => '账号不存在, 无法登录!'];
            default:
                return ['status' => false, 'msg' => '账号状态异常, 无法登录!'];
        }

        $time = time();
        $tokenData = [
            'token' => Common::getUuid(),
            'user_id' => $userLogin->user_id,
            'last_ip' => $data['last_ip'],
            'last_time' => $time,
            'token_time' => $time + 60 * 60 * 24 * 30, // 30天
            'device' => $data['device'] ?? '未知设备',
        ];

        // 获取用户 token 信息
        // $userToken = UserTokenModel::where('user_id', $userLogin->user_id)->first();

        // token 存在则更新 不存在则创建
        // if ($userToken) {

        //     $tokenData['token'] = $userToken->token;

        //     $userToken->token_time = $tokenData['token_time'];
        //     // $userToken->last_time = $tokenData['last_time']; // 不更新登录时间 避免无限登录
        //     $userToken->last_ip = $tokenData['last_ip'];
        //     $userToken->device = $tokenData['device'];

        //     // 更新token
        //     $userToken->save();
        // } else {

        // 生成token 设置token过期时间
        $userToken = UserTokenModel::create($tokenData);
        // }

        // 通过用户类型获取redis Key
        switch ($userLogin->type) {
            case 1: // 普通用户
                $key = config('rediskey')['userClientInfo'];
                break;
            case 2: // 管理员
                $key = config('rediskey')['tokenInfo'];
                break;
            case 3: // 合作用户/商家
                $key = config('rediskey')['userApplyToken'];
                break;
            default: // 未定义因此默认为普通用户
                // throw new Exception('用户类型异常, 无法登录!');
                return ['status' => false, 'msg' => '用户类型异常, 无法登录!'];
        }

        // 存入redis中
        app('redis')->hMset($key . $userLogin->user_id, $tokenData);

        return ['status' => true, 'data' => $tokenData];
    }

    /**
     * 找回密码
     * @param $guid
     * @param $data[] bind_phone
     * @param $data[] password
     * @return array
     */
    public function findPassword($data)
    {

        $userlogin = UserLoginModel::where('bind_phone', $data['bind_phone'])->first();

        // 检测用户是否存在
        if (empty($userlogin)) {
            return ['status' => false, 'msg' => '用户不存在!'];
        }

        $userlogin->password = Common::cryptString($userlogin->user_id, $data['password']);

        $res = $userlogin->save();

        return ['status' => true, 'data' => $res];
    }

    /**
     * 修改密码
     * @param $guid
     * @param $data[] old_password
     * @param $data[] password
     * @return array
     */
    public function updatePass($guid, $data)
    {

        $userlogin = UserLoginModel::where('user_id', $guid)->first();

        // 旧密码检测
        $old_password = Common::cryptString($userlogin->user_id, $data['old_password']);
        if ($old_password != $userlogin->password) {
            return ['status' => false, 'msg' => '密码错误!'];
        }

        // 新密码检测
        $password = Common::cryptString($userlogin->user_id, $data['password']);
        if ($userlogin->password == $password) {
            return ['status' => false, 'msg' => '新密码不能与旧密码相同!'];
        }

        $userlogin->password = $password;

        $res = $userlogin->save();

        return ['status' => true, 'data' => $res];
    }

    /**
     * 更新登录信息
     * @param $guid
     * @param $data
     * @return array
     */
    public function loginUpdate($guid, $data)
    {
        $newData = [];

        // 用户名重复检测
        if (@$data['username']) {

            $username = UserLoginModel::where('username', $data['username'])->first();

            if ($username && $username->user_id != $guid) {
                return ['status' => false, 'msg' => '用户名已存在!'];
            }

            $newData['username'] = $data['username'];
        }

        // 手机号重复检测
        if (@$data['bind_phone']) {

            $bind_phone = UserLoginModel::where('bind_phone', $data['bind_phone'])->first();

            if ($bind_phone && $bind_phone->user_id != $guid) {
                return ['status' => false, 'msg' => '手机号已存在!'];
            }

            $newData['bind_phone'] = $data['bind_phone'];
        }

        // 邮箱重复检测
        if (@$data['bind_email']) {

            $bind_email = UserLoginModel::where('bind_email', $data['bind_email'])->first();

            if ($bind_email) {
                return ['status' => false, 'msg' => '邮箱已存在!'];
            }

            $newData['bind_email'] = $data['bind_email'];
        }

        // 更新登录表信息
        $result = $this->updateLogin($guid, $newData);

        return ['status' => true, 'data' => $result];
    }

    /**
     * 重置密码
     * @param $guid
     * @param $data
     * @return array
     */
    public function resetPass($guid, $data)
    {
        $newData = [];

        $userlogin = $this->loginInfo($guid);

        $newData['password'] = Common::cryptString($userlogin->user_id, $data['passwords']);

        // 更新登录表信息
        $result = $this->updateLogin($guid, $newData);

        return ['status' => true, 'data' => $result];
    }

    /**
     * 退出登录
     * @param $user_id
     * @return array
     */
    public function loginOut($user_id)
    {

        // 生成token 设置token过期时间
        $result = UserTokenModel::where('user_id', $user_id)->update([
            'token' => Common::getUuid(),
            'token_time' => time(), // 过期时间设为当前时间
        ]);

        // 因为退出时不确定哪一端 清空全部redis 
        app('redis')->del(config('rediskey.tokenInfo') . $user_id);
        app('redis')->del(config('rediskey')['userClientInfo'] . $user_id);
        app('redis')->del(config('rediskey')['userApplyToken'] . $user_id);

        return ['status' => true, 'data' => $result];
    }

    /********************** 基础数据层 *********************/

    /**
     * 获取全部
     * @param $data
     * @return array
     */
    public function all($data)
    {

        // 查询条件
        $result =
            UserInfoModel::when(@$data['select'], function ($q) use ($data) {
                $q->selectRaw($data['select']);
            })
            ->when(@$data['app_id'], function ($q) use ($data) {
                $q->where('app_id', $data['app_id']);
            })
            ->when(@$data['limit'], function ($q) use ($data) {
                $q->limit($data['limit']);
            })
            ->orderBy('created_at', 'desc')
            ->get();

        return $result;
    }

    /**
     * 获取列表
     * @param $data
     * @return array
     */
    public function list($data)
    {
        $current = $data['current'] ?? 1;
        $pageSize = $data['pageSize'] ?? 10;

        // 查询条件
        $paginate = UserInfoModel::select('*')
            ->with(['userToken'])
            ->leftJoin('data_user_login as login', 'guid', 'login.user_id')
            ->when(@$data['guid'], function ($q) use ($data) {
                $q->where('guid', $data['guid']);
            })
            ->when(@$data['app_id'], function ($q) use ($data) {
                $q->where('app_id', $data['app_id']);
            })
            ->when(@$data['gender'], function ($q) use ($data) {
                $q->where('gender', $data['gender']);
            })
            ->when(@$data['role_id'], function ($q) use ($data) {
                $q->where('meta->role_id', $data['role_id']);
            })
            ->when(@$data['status'], function ($q) use ($data) {
                $q->where('login.status', $data['status']);
            })
            ->when(@$data['type'], function ($q) use ($data) {
                $q->where('login.type', $data['type']);
            })
            ->when(@$data['username'], function ($q) use ($data) {
                $q->where('login.username', $data['username']);
            })
            ->when(@$data['bind_email'], function ($q) use ($data) {
                $q->where('login.bind_email', $data['bind_email']);
            })
            ->when(@$data['bind_phone'], function ($q) use ($data) {
                $q->where('login.bind_phone', $data['bind_phone']);
            })
            ->when(@$data['nick_name'], function ($q) use ($data) {
                $q->where('nick_name', 'like', '%' . $data['nick_name'] . '%');
            })
            ->orderBy('login.id', 'desc')
            ->paginate($pageSize, ['*'], 'page', $current);

        return [
            'current' => $current,
            'data' => $paginate->items(),
            'pageSize' => $pageSize,
            'total' => $paginate->total(),
        ];
    }

    /**
     * 更新用户信息
     * @param $guid
     * @param $data
     * @return array
     */
    public function update($guid, $data)
    {

        // 查询条件
        $userInfo = UserInfoModel::where('guid', $guid)->first();

        $userInfo->nick_name = $data['nick_name'] ?? $userInfo->nick_name; // 昵称
        $userInfo->gender = $data['gender'] ?? $userInfo->gender; // 0 未知 1 男 2 女
        $userInfo->avatar = $data['avatar'] ?? $userInfo->avatar; // 头像
        $userInfo->birthday = $data['birthday'] ?? $userInfo->birthday; // 生日
        $userInfo->meta = $data['meta'] ?? $userInfo->meta; // 更多信息

        $userInfo->save();

        return $userInfo;
    }

    /**
     * 更新登录信息
     * @param $guid
     * @param $data
     * @return array
     */
    public function updateLogin($guid, $newData)
    {

        return UserLoginModel::where('user_id', $guid)->update($newData);
    }

    /**
     * 登录状态更新
     * @param $guid
     * @param $data
     * @return array
     */
    public function statusUpdate($guid, $status)
    {

        return UserLoginModel::where('user_id', $guid)->update([
            'status' => $status // 1 正常 2 禁用 3 封禁 4 注销
        ]);
    }

    /**
     * 登录信息
     * @param $guid
     * @return collection
     */
    public function loginInfo($guid)
    {

        return UserLoginModel::where('user_id', $guid)->first();
    }

    /**
     * 详情
     * @param $guid
     * @return collection
     */
    public function userInfo($guid)
    {

        // 查询详情
        $result =  UserInfoModel::where('guid', $guid)
            ->leftJoin('data_user_login as login', 'guid', 'login.user_id')
            ->select('data_user_info.*', 'login.status', 'login.bind_phone', 'login.username', 'login.bind_email')
            ->first();

        return $result;
    }
}
